package com.markhsiu.net;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.TimeUnit;

public class Acceptor extends Thread{

	private int port = 8080;
	private Selector selector;
	private ServerSocketChannel serverChannel;
	
	public Acceptor(int port) {
		super("Acceptor-thread");
		this.port = port;
		
	}
	
	@Override
	public void run() {
		try {
			selector = Selector.open();
			serverChannel  = ServerSocketChannel.open();
			serverChannel.configureBlocking(false);
			
			serverChannel.socket().bind(new InetSocketAddress( port));
			SelectionKey keyFirst = serverChannel.register(selector, SelectionKey.OP_ACCEPT, this);
			
			
			while(true){
				int readyChannels = selector.select();
				if(readyChannels == 0){
					TimeUnit.MILLISECONDS.sleep(100);
					continue;
				}
				
				Set<SelectionKey> selectionKeys = selector.selectedKeys();
				Iterator<SelectionKey> keyIterator = selectionKeys.iterator();
				while(keyIterator.hasNext()){
					SelectionKey key = keyIterator.next();
					if(key.isAcceptable()){
						 // a connection was accepted by a ServerSocketChannel.
						doAccept(key);
					} else if(key.isConnectable()){
						// a connection was established with a remote server.
						doConnect(key);
					} else if(key.isReadable()){
						// a channel is ready for reading
						doRead(key);
					} else if(key.isWritable()){
						 // a channel is ready for writing
						doWrite(key);
					}
					keyIterator.remove();
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		} 
	}
	
	/**
	 *  对新的客户端连接进行处理 
	 * @param key
	 * @throws IOException
	 */
	public void doAccept(SelectionKey key) throws IOException{
		System.out.println(" is a Acceptable");
		ServerSocketChannel serverChannel = (ServerSocketChannel) key.channel();
		SocketChannel channel = serverChannel.accept();
		channel.configureBlocking(false);
		channel.register(selector, SelectionKey.OP_READ | SelectionKey.OP_WRITE);
	}
	
	/**
	 *  写消息到客户端 
	 * @param key
	 * @throws IOException
	 */
	public void doWrite(SelectionKey key) throws IOException{
		System.out.println(" is a Writable ");
		SocketChannel channel = (SocketChannel) key.channel();
		ByteBuffer writeBuffer = ByteBuffer.wrap(" im mark server".getBytes());
		while(writeBuffer.hasRemaining()){
			channel.write(writeBuffer);
		} 
		channel.register(selector, SelectionKey.OP_READ);
	}
	
	public void doRead(SelectionKey key) throws IOException{
		System.out.println(" is  a Readable");
		SocketChannel channel = (SocketChannel) key.channel();
		
		ByteBuffer readBuffer = ByteBuffer.allocate(1024);
		while(channel.read(readBuffer) > 0){
			readBuffer.flip();
			byte[] result = new byte[readBuffer.limit()];
			readBuffer.get(result);
			System.out.println("read .. "+new String(result));
			readBuffer.clear();
		}
		channel.register(selector, SelectionKey.OP_WRITE);
		
	}
	
	/**
	 * 已连接
	 * @param key
	 */
	public void doConnect(SelectionKey key){
		System.out.println(" is a Connectable ");
	}
}
